<template>
    <n-modal
        v-model:show="showModal"
        class="custom-modal-public"
        :class="{ 'custom-modal-public-has-scroll': hasScroll }"
        :auto-focus="false"
        :mask-closable="false"
    >
        <n-card
            :style="{ width: `${width}px` }"
            :title="title"
            size="medium"
            :aria-modal="false"
        >
            <template #header-extra>
                <NIcon class="close-icon" :size="28" @click="onClose">
                    <CloseOutline />
                </NIcon>
            </template>
            <n-spin v-if="loading" :show="loading">
                <template #description> loading... </template>
            </n-spin>
            <FormTemplate
                v-else
                ref="formTemplateRef"
                :form-list="configList"
                :rules="rules"
                :form-props="formProps"
                :form-item-props="formItemProps"
            >
            </FormTemplate>
            <template #footer>
                <div class="foot">
                    <NButton @click="onClose">取消</NButton>
                    <NButton type="primary" @click="onSave">确定</NButton>
                </div>
            </template>
        </n-card>
    </n-modal>
</template>

<script setup>
import FormTemplate from '../FormTemplate/index.vue';
import { CloseOutline } from '@vicons/ionicons5';
import { addValue, queryDetails, updateValue } from '@/api/public';
import { ref, computed, watch, nextTick } from 'vue';

const emit = defineEmits(['update:modelValue', 'save-success', 'save']);
const props = defineProps({
    modelValue: {
        type: Boolean,
        default: false
    },
    // 表名
    tableName: {
        type: String,
        default: '',
        required: true
    },
    dataId: {
        type: String,
        default: ''
    },
    title: {
        type: String,
        default: ''
    },
    width: {
        type: [String, Number],
        default: '600'
    },
    formProps: {
        type: Object,
        default: () => ({})
    },
    formItemProps: {
        type: Object,
        default: () => ({})
    },
    formList: {
        type: Array,
        default: () => []
    },
    rules: {
        type: Object,
        default: () => ({})
    },
    // 手动保存
    handleSave: {
        type: Boolean,
        default: false
    },
    // 手动设置表单的每一项值
    /**
     * {
     * name:()=>'',
     * }
     */
    itemValueConfig: {
        type: Object,
        default: () => ({})
    }
});
const formTemplateRef = ref(null);
const hasScroll = ref(false);
const loading = ref(false);
const editData = ref({});
const configList = ref([]);

const showModal = computed({
    get() {
        return props.modelValue;
    },
    set(val) {
        emit('update:modelValue', val);
    }
});
const getFormData = () => formTemplateRef.value.getFormData();
const setFormData = data => formTemplateRef.value.setFormData(data);

const onClose = () => {
    showModal.value = false;
};
// 保存
const onSave = () => {
    formTemplateRef.value.formRef?.validate(err => {
        if (err) return;
        const result = getFormData();
        if (props.handleSave) {
            emit('save', result);
            return;
        }
        let api = addValue;
        if (props.dataId) {
            api = updateValue;
            result._id = editData.value._id;
        }
        api(props.tableName, result).then(res => {
            emit('save-success', res);
            showModal.value = false;
        });
    });
};
const nullVal = ['', undefined, null];
const setConfig = res => {
    configList.value.forEach(item => {
        if (props.itemValueConfig?.[item.code]) {
            item.value = props.itemValueConfig[item.code](res);
        } else {
            item.value = nullVal.includes(res[item.code])
                ? item.nullVal
                : res[item.code];
        }
    });
};
const getDetails = async () => {
    const res = await queryDetails(props.tableName, { _id: props.dataId });
    editData.value = res;
    setConfig(res);
};
const initConfig = () => {
    configList.value = props.formList;
};
defineExpose({
    getFormData,
    setFormData
});
watch(
    () => props.modelValue,
    async val => {
        if (val) {
            loading.value = true;
            initConfig();
            if (props.dataId) {
                await getDetails();
            }
            loading.value = false;
        }
    }
);
watch(
    () => loading.value,
    val => {
        if (!val) {
            nextTick(() => {
                const container = document.querySelector('.n-card__content');
                if (container) {
                    hasScroll.value =
                        container.scrollHeight > container.clientHeight;
                }
            });
        }
    }
);
</script>
<style lang="less">
.custom-modal-public {
    .n-card-header {
        padding: 12px 20px;
        border-bottom: 1px solid var(--grey-300);
        box-sizing: border-box;
    }

    .n-card__content {
        padding: 0 34px;
        max-height: calc(100vh - 220px);
        overflow-y: auto;
    }

    .n-card__footer {
        padding: 12px 20px;
    }

    &-has-scroll {
        .n-card__footer {
            box-shadow: 0 -3px 3px 0 rgba(0, 0, 0, 0.1);
        }
    }
}
</style>
<style lang="less" scoped>
:deep(.n-form) {
    margin-top: 24px;
}

.close-icon {
    cursor: pointer;
    border-radius: 4px;

    &:hover {
        background-color: var(--grey-300);
    }
}

.foot {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}
</style>
